#include <avr/io.h>
#include "pins.h"

#define VERSION         "128.12V"
#define IDENT           "EEPROM128V2"

// Buffers
#define BUFF_LEN 128
#define delay60ns  {asm volatile("nop");}
#define delay125ns {asm volatile("nop");asm volatile("nop");}
#define delay250ns {asm volatile("nop");asm volatile("nop");asm volatile("nop");asm volatile("nop");}
#define delay500ns {delay250ns;delay250ns;}

uint8_t pageBuffer[256];                      // page buffer 使用256字节 具体根据芯片读取
char    cmdBuffer[22];                        // command buffer
//注意修改 readCommand

uint8_t  chip29length = 9;
uint32_t chips29[] = {29512,29010,29020,29040,29011,29021,29041,29022,29042};

//--------------------------------------------

// 判断是否是29
boolean check29InChips(uint32_t chipId){
    for(int i=0;i<chip29length;i++){
        if(chips29[i]==chipId){
            return true;
        }
    }
    return false;
}


void setup() {
  //初始化
  pinMode(chip_CE, OUTPUT);
  pinMode(chip_OE, OUTPUT);
  pinMode(chip29WE, OUTPUT);
  digitalWrite(chip29WE, HIGH);
  digitalWrite(chip_CE, HIGH);
  digitalWrite(chip_OE, HIGH);

  //高压不输出
  pinMode(V_OE, OUTPUT);
  digitalWrite(V_OE, LOW);
  pinMode(V_A9, OUTPUT);
  digitalWrite(V_A9, LOW);
  pinMode(V_A15, OUTPUT);
  digitalWrite(V_A15, LOW);
  pinMode(V_A19, OUTPUT);
  digitalWrite(V_A19, LOW);
  pinMode(V_A17, OUTPUT);
  digitalWrite(V_A17, LOW);
  pinMode(V_VCC, OUTPUT);
  digitalWrite(V_VCC, LOW);

  //默认选中29芯片
  chip29();
  setAddress29(0);
  
  //28脚WE
  digitalWrite(chip28WE, HIGH);

//  Serial.begin(1000000);
  Serial.begin(115200);
}




//------------------------------------------------------------------

void loop() {
  //程序判断用
  Serial.println(F("Ready"));
  //switchChip(0);


  
  digitalWrite(chip_CE, HIGH);
  
  digitalWrite(V_OE, LOW);
  digitalWrite(V_A9, LOW);
  digitalWrite(V_A15, LOW);
  digitalWrite(V_A19, LOW);
  digitalWrite(V_A17, LOW);
  digitalWrite(V_VCC, LOW);


  //r W29040 00000 fffff
  //0 2+6    9+5   15+5
  readCommand();
  char cmd = cmdBuffer[0];                      //指令
  uint32_t chipId    = hexChip(cmdBuffer + 2);  //芯片
  uint8_t  startPage = hexDigit(cmdBuffer[9]);
  uint32_t startAddr = hexWord(cmdBuffer + 10); //开始地址
  uint8_t  endPage   = hexDigit(cmdBuffer[15]);
  uint32_t endAddr   = hexWord(cmdBuffer + 16); //结束地址

  // 28pin 只能支持到 0xffff
  // 32pin 支持到 0x7ffff
  startAddr &= 0xffff;
  endAddr &= 0xffff;
  startPage &= 0x7;
  endPage   &= 0x7;
  endPage = endPage < startPage ? startPage : endPage;

  startAddr = (startPage * 65536) + startAddr;
  endAddr   = (endPage * 65536) + endAddr;

  endAddr = endAddr < startAddr ? startAddr : endAddr;

  // 数据长度
  //  uint8_t  pageLength = endPage - startPage + 1;
  uint32_t dataLength = endAddr - startAddr + 1;


  // 初始化地址
//  if(startAddr==0){
//    setAddress29(0);
//  }

//  if (cmd != 'w' || startAddr==0) {
//    switchChip(chipId);
//  }

  switch (cmd) {
    case 'i':   Serial.println(IDENT); break;
    case 'v':   Serial.println(VERSION); break;
    case 't':   Serial.println("Ready"); break;
    case 'c':   checkChip(chipId); break;
    case 'l':   //加锁
      if (chipId==2864||chipId==28256) { //2864 28256
        enableWriteProtection28(); break;
      } else if (check29InChips(chipId)) { //29
        enableWriteProtection29(); break;
      } else {
        Serial.println(F("Lock not support")); break;
      }
      break;
    case 'u':   //解锁
      if (chipId==2864||chipId==28256) { //28
        disableWriteProtection28();
        Serial.println(F("unlock ok"));
        break;
      } else if (check29InChips(chipId)) { //29
        disableWriteProtection29();
        Serial.println(F("unlock ok"));
        break;
      } else {
        Serial.print(F("Unlock not support "));
        Serial.println(chipId);
        break;
      }
      break;
    case 'e':   //擦片
      if (chipId==2864||chipId==28256) { //2864 28256
        //                  eraser28();
        break;
      } else if (check29InChips(chipId)) { //29
        eraser29();
        break;
      } else if (chipId==2764||chipId==27128||chipId==27256||chipId==27512||
                chipId==27010||chipId==27020||chipId==27040||chipId==27080 ){
        eraser27(chipId);
      } else {
        Serial.println(F("Eraser not support"));
      }
      break;
    case 'r':
      if (chipId==2716||chipId==2732) { //27-24p
          read27_24P(startAddr, dataLength,chipId);
          break;
      } else if (chipId==2764||chipId==27128||chipId==27256||chipId==27512) { //27-28p
          read27_28P(startAddr, dataLength,chipId);
          break;
      } else if (chipId==27010||chipId==27020||chipId==27040||chipId==27080) { //27-32p
          read27_32P(startAddr, dataLength,chipId);
          break;
      } else if (chipId==2816) { //2816
          read2816(startAddr, dataLength,chipId);
          break;
      } else if (chipId==2864||chipId==28256) { //28
          read28_28P(startAddr, dataLength,chipId);
          break;
      } else if (check29InChips(chipId)) { //29
          read29(startAddr, dataLength);
          break;
      } else {
        Serial.println(F("Read not support")); break;
      }
      break;
    case 'w':
      if (chipId==2816) { //2816
          write2816(startAddr, dataLength,chipId);
          break;
      } else if (chipId==2817||chipId==2864||chipId==28256) { //28
          write28(startAddr, dataLength,chipId);
          break;
      } else if (check29InChips(chipId)) { //29
          write29(startAddr, dataLength, chipId);
          break;

//      } else if (chipId==2716||chipId==2732) { //27-24p
//      } else if (chipId==2764||chipId==27128||chipId==27256||chipId==27512) { //27-28p
//      } else if (chipId==27010||chipId==27020||chipId==27040||chipId==27080) { //27-32p

      } else {
        Serial.print(F("Write not support,chipId:"));
        Serial.println(chipId);
        break;
      }
      break;

    //测试用
    //测试命令
    //x  29010 00000 7ffff 00
    case 'x':
      Serial.println(cmdBuffer);
      Serial.print(chipId); Serial.print(" ");
      Serial.print(startAddr); Serial.print("-");
      Serial.print(endAddr); Serial.print(" ");
      Serial.print(dataLength); Serial.print(" ");
      Serial.println("");
      //                Serial.print("page: ");
      //                Serial.print(startPage);Serial.print(" ");
      //                Serial.print(endPage);Serial.print(" ");
      //                Serial.println("");

      break;

    case 'a':
      setAddress29(startAddr);
      break;

    default:
      break;
  }


  //执行结束恢复
  setAddress29(0);
  //28脚WE
  digitalWrite(chip28WE, HIGH);
  //24脚WE
  digitalWrite(C2816_WE, HIGH);
  
}

//------------------------------------------------------------------

void read29(uint32_t addr, uint32_t count) {
  //reset29();

  delay(1);

  read_mode();
  digitalWrite(chip29WE, HIGH);
  digitalWrite(chip_CE, LOW);
  digitalWrite(chip_OE, LOW);

  while (count-- > 0) {
    Serial.write(readDataByte29(addr++));
  }

  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);
}

// 根据地址读取数据
byte readDataByte29(uint32_t addr) {
  setAddress29 (addr);
  delay125ns;
  return get_data();
}


void read2816(uint32_t addr, uint32_t count,uint32_t chipId) {
  chip28_24P();
  read_mode();
  digitalWrite(chip28WE, HIGH);
  digitalWrite(chip_CE, LOW);
  digitalWrite(chip_OE, LOW);
  delay(10);
  while (count-- > 0) {
    setAddress28_24P (addr++);
    delay125ns;
    Serial.write(get_data());
  }
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);
}

void read28_28P(uint32_t addr, uint32_t count,uint32_t chipId) {
  switchChip(chipId);
  read_mode();
  digitalWrite(chip28WE, HIGH);
  digitalWrite(chip_CE, LOW);
  digitalWrite(chip_OE, LOW);
  delayMicroseconds(1);
  while (count-- > 0) {
    setAddress28_28P (addr++);
    delay125ns;
    Serial.write(get_data());
  }
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);
}

void read27_32P(uint32_t addr, uint32_t count,uint32_t chipId) {
  switchChip(chipId);
  read_mode();
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, LOW);
  delayMicroseconds(1);
  while (count-- > 0) {
    setAddress27_32P (addr++,chipId);
    digitalWrite(chip_OE, LOW);
    delay250ns;
    Serial.write(get_data());
    digitalWrite(chip_OE, HIGH);
  }
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);
}

void read27_28P(uint32_t addr, uint32_t count,uint32_t chipId) {
  switchChip(chipId);
  read_mode();
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, LOW);
  delayMicroseconds(1);
  while (count-- > 0) {
    setAddress27_28P (addr++,chipId);
    digitalWrite(chip_OE, LOW);
    delay250ns;
    Serial.write(get_data());
    digitalWrite(chip_OE, HIGH);
  }
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);
}

void read27_24P(uint32_t addr, uint32_t count,uint32_t chipId) {
  switchChip(chipId);
  read_mode();
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, LOW);
  delayMicroseconds(1);
  while (count-- > 0) {
    setAddress27_24P (addr++,chipId);
    digitalWrite(chip_OE, LOW);
    delay250ns;
    Serial.write(get_data());
    digitalWrite(chip_OE, HIGH);
  }
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);
}

// 根据地址读取数据
//byte readDataByte28(uint32_t addr) {
//  setAddress28_28P (addr);
//  delay125ns;
//  return get_data();
//}


//---------------------------------------------

//void reset29() {
//  chip29();
//  write_mode();
//  setByte29(0,0xf0);
//  read_mode();
//}

// 29 指令使用
void setByte29(uint32_t address, byte dataa) {
  set_data(dataa);
  setAddress29(address);
  delay125ns;
  digitalWrite(chip29WE, LOW);
  delay125ns;
  digitalWrite(chip29WE, HIGH);
}

// 28
void setByte28(uint32_t address, byte dataa) {
  set_data(dataa);
  setAddress28_28P (address);
  delay125ns;
  digitalWrite(chip28WE, LOW);
  delay125ns;
  digitalWrite(chip28WE, HIGH);
}

// 27
//void setByte27(uint32_t address, byte data){
//  set_data(data);
//  setAddress27(address);
//  digitalWrite(chip_WE, LOW);
//  delayMicroseconds(2);
//  digitalWrite(chip_WE, HIGH);
//}


//----------------------------------------------


void write29(uint32_t addr, uint32_t total, uint32_t chipId) {
  int pageLength = BUFF_LEN;
  if (chipId==29022||chipId==29042){
    pageLength = 256;
  }
  
  for (int i = 0; i < pageLength; i++) {
    while (!Serial.available());
    pageBuffer[i] = Serial.read();
  }

  //reset29();

  write_mode();
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip29WE, HIGH);
  digitalWrite(chip_CE, LOW);
  delay125ns;


  // A29 MX29 SSF39
  if (chipId==29010||chipId==29020||chipId==29040) {

    delayMicroseconds(10);
    
    for (uint8_t i = 0; i < BUFF_LEN; i++) {
      setByte29 (0x5555, 0xaa);
      setByte29 (0x2aaa, 0x55);
      setByte29 (0x5555, 0xa0);
      setByte29 (addr+i, pageBuffer[i]);
      //延时以兼容MX29写入
      delayMicroseconds(1);
    }
    delay(10);
    // Winbond 29 特殊的 128 字节写入
  } else if (chipId==29512||chipId==29011||chipId==29021||chipId==29041) {
    setByte29 (0x5555, 0xaa);
    setByte29 (0x2aaa, 0x55);
    setByte29 (0x5555, 0xa0);
    for (uint8_t i = 0; i < BUFF_LEN; i++) {
      setByte29(addr+i, pageBuffer[i]);
      delay250ns; 
    }
    delay(10);

  // AT29C020 AT29C040 为 256 字节每页 写入数据 每页需要在150us内写完
  } else if (chipId==29022||chipId==29042) {
    setByte29 (0x5555, 0xaa);
    setByte29 (0x2aaa, 0x55);
    setByte29 (0x5555, 0xa0);
    for (uint16_t i = 0; i < 256; i++) {
      setByte29(addr+i, pageBuffer[i]);
      delay125ns;
    }
    delay(10);
    // 其他芯片报错
  } else {
    Serial.print(F("Not support type for write"));
    return;
  }

  digitalWrite(chip29WE, HIGH);
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);
  delay500ns;

  check_buff29(addr,chipId);
}

void check_buff29(uint32_t addr,uint32_t chipId){

  int pageLength = BUFF_LEN;
  if (chipId==29022||chipId==29042){
    pageLength = 256;
  }
  
  read_mode();
  //读数据校验
  digitalWrite(chip29WE, HIGH);
  digitalWrite(chip_CE, LOW);
  digitalWrite(chip_OE, LOW);
  delay125ns;
  boolean has_error = false;

  for(int i=0;i<pageLength ;i++){
    uint8_t rd = readDataByte29(addr+i);
    if(pageBuffer[i]!=rd){
      Serial.print("0x");
      Serial.print(addr+i,HEX);
      Serial.print("=");
      Serial.print(rd,HEX);
      Serial.print(",not:");
      Serial.print(pageBuffer[i],HEX);
      Serial.print(" ");
      has_error = true;
    }
  }

  if(has_error){
    Serial.print("_type:error");
//    Serial.println(type);
//    Serial.print(type);
  }
  digitalWrite(chip_CE, HIGH);
  digitalWrite(chip_OE, HIGH);

}

//--------------------------------------------------------
// 擦除29
void eraser29() {
  chip29();
  delay(1);
  write_mode();                            // set data bus pins as output
  digitalWrite(chip29WE, HIGH);
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, LOW);
  delay125ns;
  //reset chip
  //setByte29 (0x0000, 0xf0);
  delay125ns;
  setByte29 (0x5555, 0xaa);                     // write code sequence
  setByte29 (0x2aaa, 0x55);
  setByte29 (0x5555, 0x80);
  setByte29 (0x5555, 0xaa);
  setByte29 (0x2aaa, 0x55);
  setByte29 (0x5555, 0x10);
  delay125ns;
  digitalWrite(chip_CE, HIGH);
  delay(20);                                  // wait write cycle time
  read_mode();
}


// 擦除
void eraser27(uint32_t chipId){
  // 写模式 写0
  write_mode();
  set_data(0xff);
  delay250ns;
  digitalWrite(chip_OE,HIGH);

  if(chipId==27080||chipId==27512){
    if(chipId==27512){
      // VCC 高电平
      digitalWrite(VCC_28PIN,HIGH);
    }
    //A9高电平
    digitalWrite(Add_9, HIGH);
    digitalWrite(V_A9,HIGH);
    digitalWrite(V_OE,HIGH);

    delay125ns;
    digitalWrite(chip_CE,LOW);
    delay(105);
    digitalWrite(chip_CE,HIGH);
    delay125ns;

  }else if(chipId==27040){
    //A9高电平
    setAddress27_32P(0x0200,chipId);
    digitalWrite(V_A9,HIGH);
    digitalWrite(V_A19,HIGH);
    digitalWrite(chip_CE,LOW);
    delay(105);
    digitalWrite(V_A9,LOW);
    digitalWrite(V_A19,LOW);
  }else if(chipId==27010||chipId==27020){
    //A9高电平
    digitalWrite(Add_9, HIGH);
    //PGM=1
    digitalWrite(A27_32P_18,HIGH);

    digitalWrite(V_A9,HIGH);
    digitalWrite(V_A19,HIGH);
    digitalWrite(chip_CE,LOW);

    delay125ns;
    //PGM=0
    digitalWrite(A27_32P_18,LOW);
    delay(105);
    digitalWrite(A27_32P_18,HIGH);
    delay125ns;
  }else if(chipId==27256){
    //A9高电平
    digitalWrite(Add_9, HIGH);
    digitalWrite(V_A9,HIGH);
    digitalWrite(V_A15,HIGH);

    delayMicroseconds(1);
    digitalWrite(chip_CE,LOW);
    delay(105);
    digitalWrite(chip_CE,HIGH);
  }else if(chipId==2764||chipId==27128){
    //这个容量可能没有电擦除
    digitalWrite(V_A9,HIGH);
    digitalWrite(V_A15,HIGH);
    //PGM=1
    //digitalWrite(A_14,HIGH);
    setAddress27_28P (0x4000,chipId);
    digitalWrite(chip_CE,LOW);

    //PGM=0
    //digitalWrite(A_14,LOW);
    setAddress27_28P (0,chipId);
    delay(105);
    //digitalWrite(A_14,HIGH);
    setAddress27_28P (0x4000,chipId);
    digitalWrite(chip_CE,HIGH);
//  }else if(chipId==2817||chipId==2863||chipId==2864||chipId==28256){
//    if(chipId==2864||chipId==28256){
//      unlock28();
//      read_mode();
//      digitalWrite(chip_CE,HIGH);
//    }
//    // WE 高电平
//    setAddress (0x8000,chipId);
//    // VCC 高电平
//    digitalWrite(VCC_28PIN,HIGH);
//
//    digitalWrite(chip_CE,LOW);
//    digitalWrite(V_OE,HIGH);
//
//    delayMicroseconds(1);
//    //digitalWrite(A_14,LOW);
//    setAddress (0x0,chipId);
//    delay(15);//最少10毫秒
//    //digitalWrite(A_14,HIGH);
//    setAddress (0x8000,chipId);
//
//    delayMicroseconds(1);
//    digitalWrite(chip_CE,HIGH);
//    delay(100);
//    // VCC 高电平
//    digitalWrite(VCC_28PIN,LOW);
//    delay125ns;
//  }else if(chipId==2816){
//    // WE 高电平 A11
//    // VCC A13
//    setAddress28_24P (0x2800);
//    
//    digitalWrite(VCC_24PIN,HIGH);
//    digitalWrite(C2816_WE,HIGH);
//    
//
//    digitalWrite(chip_CE,LOW);
//    digitalWrite(V_OE,HIGH);
//
//    delay125ns;
//    setAddress (0x2000,chipId);
//    delay(15);//最少10毫秒
//    setAddress28_24P (0x2800);
//
//    digitalWrite(chip_CE,HIGH);
//    delay125ns;
  }


  digitalWrite(chip_OE,LOW);
  digitalWrite(V_A19,LOW);
  digitalWrite(V_A15,LOW);
  digitalWrite(V_OE,LOW);
  digitalWrite(V_A9,LOW);
  setAddress29(0);
  delay(10);
  read_mode();
  digitalWrite(chip_OE,HIGH);
  digitalWrite(chip_CE,HIGH);
  Serial.println("ok");
}




void read29Sid() {
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, LOW);
  write_mode();                               // set data bus pins as output
  //reset
  //setByte29 (0x0000, 0xf0);
  delay125ns;
  setByte29 (0x5555, 0xaa);                     // write code sequence
  setByte29 (0x2aaa, 0x55);
  setByte29 (0x5555, 0x90);
  delay125ns;
  read_mode();
  setAddress29(0);
  digitalWrite(chip_OE, LOW);
  delay125ns;
  Serial.println(get_data());
  setAddress29(1);
  Serial.println(get_data());
  //write_mode();
  //setByte29 (0x0000, 0xf0);
  read_mode();
  digitalWrite(chip_CE, HIGH);
  delay(50);                                  // wait write cycle time
}


// 擦除27
/*
  void eraser27(){
  setAddress (0x200);
  // 写模式 写0
  write_mode();
  write_data_bus(0xff);
  delayMicroseconds(1);
  digitalWrite(V_A9,HIGH);
  digitalWrite(V_OE,HIGH);
  delayMicroseconds(1);
  digitalWrite(chip_CE,LOW);
  delay(100);
  digitalWrite(chip_CE,HIGH);
  delayMicroseconds(5);
  digitalWrite(chip_OE,LOW);
  digitalWrite(V_OE,LOW);
  digitalWrite(V_A9,LOW);
  setAddress (0);
  delay(10);
  read_mode();
  digitalWrite(chip_OE,HIGH);
  }
*/

// 读取芯片信息
/*
  void read27Sid(){
  read_mode();
  digitalWrite(chip_CE,LOW);
  setAddress(0);
  digitalWrite(V_A9,HIGH);
  digitalWrite(chip_OE,LOW);
  delayMicroseconds(2);
  digitalWrite(chip_OE,HIGH);
  delayMicroseconds(1);
  Serial.write(get_data());//输出
  setAddress(1);

  digitalWrite(chip_OE,LOW);
  delayMicroseconds(1);
  Serial.write(get_data());//输出
  digitalWrite(chip_OE,HIGH);
  digitalWrite(chip_CE,HIGH);
  digitalWrite(V_A9,LOW);
  }
*/

// 写入
/*
  void write27(uint32_t addr, uint32_t total){
  uint32_t address = addr;
  while(total>0){
    for (uint8_t i=0; i<BUFF_LEN; i++) {
      while (!Serial.available());
      pageBuffer[i] = Serial.read();
    }
    writePage27(address,BUFF_LEN);
    address += BUFF_LEN;
    total -= BUFF_LEN;
  }
  }
*/



void write2816(uint32_t addr, uint32_t count,uint32_t chipId) {
  for (uint8_t i = 0; i < 64; i++) {
    while (!Serial.available());
    pageBuffer[i] = Serial.read();
  }

  chip28_24P();

  write_mode();
  delay(10);
  
  digitalWrite(chip_OE, HIGH);
  digitalWrite(C2816_WE, HIGH);
  digitalWrite(chip_CE, LOW);

  for (uint8_t i = 0; i < 64; i++) {
    set_data(pageBuffer[i]);
    setAddress28_24P(addr+i);
    delay(2);
    digitalWrite(C2816_WE, LOW);
    delayMicroseconds(2);
    digitalWrite(C2816_WE, HIGH);
    delay(10);
  }

  digitalWrite(C2816_WE, HIGH);
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);

  delay125ns;

//  check_buff28(addr);

  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);
  delay125ns;
}

void write28(uint32_t addr, uint32_t count,uint32_t chipId) {
//  for (uint8_t i = 0; i < BUFF_LEN; i++) {
//    while (!Serial.available());
//    pageBuffer[i] = Serial.read();
//  }
  for (uint8_t i = 0; i < 64; i++) {
    while (!Serial.available());
    pageBuffer[i] = Serial.read();
  }

  chip28_28P();
  
  //地址0
  if(addr==0){
    disableWriteProtection28();
  }

  write_mode();
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip28WE, HIGH);
  digitalWrite(chip_CE, LOW);

  for (uint8_t i = 0; i < 64; i++) {
    setByte28 (addr+i, pageBuffer[i]);
    // 根据文档延时2毫秒
    if(chipId==2817||chipId==2864){
      delay(2);
    }
  }

  digitalWrite(chip28WE, HIGH);
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);

  //批量写入后需要等待10ms
  delay(10);
  
  check_buff28(addr);
  
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, HIGH);
  delay125ns;

}


void check_buff28(uint32_t addr){
  //读数据校验
  digitalWrite(chip28WE, HIGH);
  digitalWrite(chip_CE, LOW);
  read_mode();
  boolean has_error = false;
  for(int i=0;i<64 ;i++){
    digitalWrite(chip_OE, LOW);
    setAddress28_28P (addr+i);
    delay125ns;
    uint8_t rd = get_data();
    if(pageBuffer[i]!=rd){
      Serial.print("0x");
      Serial.print(addr+i,HEX);
      Serial.print("=");
      Serial.print(rd,HEX);
      Serial.print(",not:");
      Serial.print(pageBuffer[i],HEX);
      Serial.print(" ");
      has_error = true;
    }
    digitalWrite(chip_OE, HIGH);
  }
  if(has_error){
    Serial.print("_");
  }
  
}

void disableWriteProtection28(){
  chip28_28P();
  digitalWrite(chip28WE, HIGH);
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, LOW);
  write_mode();
  delay125ns;
  setByte28 (0x5555, 0xaa);
  setByte28 (0x2aaa, 0x55);
  setByte28 (0x5555, 0x80);
  setByte28 (0x5555, 0xaa);
  setByte28 (0x2aaa, 0x55);
  setByte28 (0x5555, 0x20);
  digitalWrite(chip_CE, HIGH);
  read_mode();                             // release data bus (set as input)
  delay(10);                                  // wait write cycle time
}

void enableWriteProtection28() {
  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, LOW);
  write_mode();                            // set data bus pins as output
  setByte28 (0x5555, 0xaa);
  setByte28 (0x2aaa, 0x55);
  setByte28 (0x5555, 0xa0);
  digitalWrite(chip_CE, HIGH);
  read_mode();                             // release data bus (set as input)
  delay(10);                                  // wait write cycle time
}

// ----------------------------------------

// 6字节代码关闭软保护
void disableWriteProtection29() {
  //  digitalWrite(chip_OE, HIGH);
  digitalWrite(chip_CE, LOW);
  write_mode();                            // set data bus pins as output
  //reset
  //setByte29 (0x0000, 0xf0);
  delay125ns;
  setByte29 (0x5555, 0xaa);                     // write code sequence
  setByte29 (0x2aaa, 0x55);
  setByte29 (0x5555, 0x80);
  setByte29 (0x5555, 0xaa);
  setByte29 (0x2aaa, 0x55);
  setByte29 (0x5555, 0x20);
  digitalWrite(chip_CE, HIGH);
  read_mode();                             // release data bus (set as input)
  delay(10);                                  // wait write cycle time
}

// write the special three-byte code to turn on software data protection
void enableWriteProtection29() {
  digitalWrite(chip_CE, LOW);
  write_mode();                            // set data bus pins as output
  //reset
  //setByte29 (0x0000, 0xf0);
  delay125ns;
  setByte29 (0x5555, 0xaa);                     // write code sequence
  setByte29 (0x2aaa, 0x55);
  setByte29 (0x5555, 0xa0);
  digitalWrite(chip_CE, HIGH);
  read_mode();                             // release data bus (set as input)
  delay(10);                                  // wait write cycle time
}

// 批量写27数据 从缓存读取
/*
  void writePage27(uint32_t address, uint32_t count){

  write_mode();
  delayMicroseconds(1);

  digitalWrite(V_OE,HIGH);
  delayMicroseconds(5);
  for(uint8_t i=0; i<count; i++){
    write_byte27(address++,pageBuffer[i]);
  }

  digitalWrite(chip_OE,LOW);
  digitalWrite(V_OE,LOW);
  delayMicroseconds(5);
  digitalWrite(chip_OE,HIGH);
  read_mode();
  }
*/

// 写入byte，需要OE高，改变CE写入数据
/*
  void write_byte27(uint32_t address, uint8_t data) {
  setAddress27(address);
  write_data_bus(data);
  delayMicroseconds(5);
  digitalWrite(chip_CE, LOW);
  delayMicroseconds(105);
  digitalWrite(chip_CE, HIGH);
  }
*/
